package cn.caplike.demo.netty.http.channel;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

import java.net.URI;
import java.net.URISyntaxException;

/**
 * Description:
 *
 * @author LiKe
 * @version 1.0.0
 * @date 2021-11-26 17:45
 */
public class TestHttpServerChannelInboundHandler extends SimpleChannelInboundHandler<HttpObject> {

    /**
     * 读取客户端发过来的请求并且对客户端进行响应的方法
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws URISyntaxException {

        // 不应执行耗时操作:
        // 1.使用自己定义的业务线程池
        // 2.借助Netty提供的向ChannelPipeline添加ChannelHandler时,调用的addLast方法来传递EventExecutor.默认调用addLast(handler),handler中的回调方法都是由I/O线程执行

        System.out.println(ctx.channel().remoteAddress());

        if (msg instanceof HttpRequest) {
            HttpRequest httpRequest = (HttpRequest) msg;
            System.out.println("请求方法名: " + httpRequest.method().name());

            URI uri = new URI(httpRequest.uri());
            if ("/favicon.ico".equals(uri.getPath())) {
                System.out.println("请求 favicon.ico");
                return;
            }

            // 响应内容
            ByteBuf content = Unpooled.copiedBuffer("Hello World", CharsetUtil.UTF_8);
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);

            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());

            ctx.writeAndFlush(response);

            // ctx.channel().close(); 确保关闭连接, 这样才会在每次请求后调用 inactive 和 unregistered, http 1.1 keep-alived
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        System.out.println("Channel active");
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        super.channelRegistered(ctx);
        System.out.println("Channel registered");
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        super.handlerAdded(ctx);
        System.out.println("Handler added");
    }

    // ~ ↓ 注意观察浏览器(访问后关闭标签页)和命令行curl时不同的行为
    // 不同于其他容器, 使用 Netty 可以手动关闭连接 (从服务器的角度去关闭)

    // Chrome:
    // Handler added
    // Channel registered
    // Channel active
    // 请求方法名: GET
    // Channel inactive
    // Channel unregistered
    // 请求方法名: GET
    // 请求 favicon.ico

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        System.out.println("Channel inactive");
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        super.channelUnregistered(ctx);
        System.out.println("Channel unregistered");
    }
}
